home *** CD-ROM | disk | FTP | other *** search
/ CD PowerPlay 10 / CD Powerplay Issue 10 (February 1996).iso / hints / onefall / omfutl / utilscom / afs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-08-30  |  7.0 KB  |  273 lines

  1. const char *Version=
  2. "AFS Version 1 - AF string finder for One Must Fall 2097 .AF files\n"
  3. "By Kenneth F. Henderson Jr. (71672,1777)";
  4. /*
  5.  This code is, of course, provided AS IS, with no waranty or anything else.
  6. Copy it, rewrite it, use it, FUBAR it, whatever you like (I would prefer that
  7. you include the above credits if you redistribute it, BTW), however no matter
  8. what happens none of the aforementioned people can be held responsible, whether
  9. your hard disk crashes, your computer dies, OMF decides to cheat on you every
  10. time you play, or anything else.  <grin>
  11.  
  12.  WARNING: The Borland C++ project file that accompanies this code turns
  13. 386 instructions ON, on the premise that since OMF requires a 386, all
  14. machines running this code will have at least a 386.  The included .COM file
  15. was compiled using this project file, so it may very well hang (or worse)
  16. on a lesser machine unless recompiled with the option set down to whatever
  17. you're using.
  18.  
  19.  For basic usage instructions, just run the program with no parameters.
  20.  
  21.  This program extracts the location and contents of everything that looks like
  22. an AF move string or keystroke sequence from .AF files.  The output format
  23. should be largely self-explanitory.  "M" is a move string which fits perfectly
  24. within its field, without a null.  "m" is a move string which has a null tacked
  25. on the end - typically a move executed by the opponent when hit.  "K" is a
  26. keystroke.
  27.  
  28.  To create a full set of AFS files for the basic AFs, first make sure you're
  29. using your original .AF files.  Then run the AFSAll.Bat batch file included.
  30. It will run AFS on each Fightr*.AF file, and then make the resulting .AFS files
  31. read-only so you don't accidentally overwrite them.  The process should take
  32. about 5-10 minutes and should only need to be done once, unless the .AF files
  33. change.  (So far, the only changes have been trivial keystroke modifications
  34. which are documented in my FAQ.)  Assuming you backup the .ZIP file this came
  35. in, you can then delete AFSAll.Bat to save space.
  36.  
  37. Below is the actual C source code.  Hackers only.  B-)
  38. */
  39. #include <stdio.h>
  40. #include <stdlib.h>
  41. #include <string.h>
  42. #include <ctype.h>
  43. #include <alloc.h>
  44.  
  45. //  Return codes (RET_)
  46. //These codes may change from version to version
  47. //If you use them, always check for changes when you get a new version
  48. #define    RET_Normal    0
  49. #define    RET_BadParms    -1
  50. #define    RET_BadFile    -2
  51. #define    RET_BadClose    -3
  52. #define    RET_OutOfMemory    -4
  53.  
  54. const char    ValidH=    '~';    //Highest valid character
  55. const char    ValidL=    ' ';    //Lowest valid character
  56.  
  57. int    FindStrings(FILE *FileIn,FILE *FileOut,
  58.         unsigned char *Buffer,size_t BufferSize)
  59. {
  60.     unsigned char    c,*d,*dmax=Buffer+BufferSize,CouldBeMove,CouldBeKeys;
  61.     unsigned long    FileSize,FilePos=0,StrLoc;
  62.     unsigned int    StrSize;
  63.  
  64.     //Get length of input file
  65.     fseek(FileIn,0,SEEK_END);
  66.     FileSize=ftell(FileIn);
  67.     fseek(FileIn,0,SEEK_SET);
  68.  
  69. while(FilePos<FileSize)
  70. {
  71.     c=fgetc(FileIn);
  72.     FilePos++;
  73.  
  74.     //Ignore chars outside 21-7E
  75.     if(c>ValidH || c<ValidL)
  76.         continue;
  77.  
  78.     //Reset buffer
  79.     d=Buffer;
  80.     StrLoc=FilePos-1;    //PREVIOUS character
  81.     CouldBeMove=1;        //Used as Boolean
  82.     CouldBeKeys=0;        //Used as size of keystroke
  83.  
  84.     //Store char
  85.     *(d++)=c;
  86.  
  87.     //Inner loop: Scan string
  88.     while(1)
  89.     {
  90.         //See if char is not found in AF move strings
  91.         if( !isalnum(c) && (c!='-') && (c!='+') )
  92.             CouldBeMove=CouldBeKeys=0;
  93.         else
  94.         {
  95.             //If it could be found in a move, it could be found
  96.             //in a keystroke.  Check for keystroke
  97.             if(!CouldBeKeys)
  98.             {
  99.                 if( (c=='P') || (c=='K') )
  100.                     CouldBeKeys=1;
  101.             }
  102.             else if( isdigit(c) )
  103.                 CouldBeKeys++;
  104.             else
  105.                 CouldBeKeys=0;
  106.         }
  107.  
  108.         //Check for end of file
  109.         if( FilePos>=FileSize )
  110.             break;
  111.  
  112.         //Check for end of buffer
  113.         if(d>=dmax)
  114.         {
  115.             printf("String at %08lX too long to process!\n",StrLoc);
  116.             break;
  117.         }
  118.  
  119.         //Get next char
  120.         c=fgetc(FileIn);
  121.         FilePos++;
  122.         *(d++)=c;
  123.  
  124.         //Upon reaching end of string, test and write
  125.         if(c>ValidH || c<ValidL)
  126.         {
  127.             //Null terminate (decrement because of above)
  128.             *(--d)=0;
  129.  
  130.             //Good place to check record keeping
  131.             if(FilePos!=ftell(FileIn))
  132.                 puts("File position failed consistency check!");
  133.  
  134.             //Get what could be a field size
  135.             fseek(FileIn,StrLoc-2,SEEK_SET);
  136.             fread(&StrSize,1,sizeof(StrSize),FileIn);
  137.             fseek(FileIn,FilePos,SEEK_SET);
  138.  
  139.             //AF move strings must end in a digit and contain at
  140.             //least one '-'
  141.             if(    CouldBeMove        &&
  142.                 isdigit(*(d-1))        &&
  143.                 strchr(Buffer,'-')    )
  144.             {
  145.                 int    i=strlen(Buffer);
  146.  
  147.                 //Check for valid size
  148.                 if(StrSize==i)
  149.                 {
  150.                     fprintf(FileOut,"%08lX:M:%s\n",
  151.                         StrLoc,Buffer);
  152.                     putchar('.');
  153.                     break;
  154.                 }
  155.                 //Check for valid size + null - commonly seen
  156.                 //in hit frame sequences.  Odd.
  157.                 else if(StrSize==i+1 && !c)
  158.                 {
  159.                     fprintf(FileOut,"%08lX:m:%s\n",
  160.                         StrLoc,Buffer);
  161.                     putchar('.');
  162.                     break;
  163.                 }
  164.             }
  165.  
  166.             //Keystrokes must have a double-null and be 1-20 chars
  167.             if(    CouldBeKeys            &&
  168.                 !c                &&
  169.                 !(FilePos++,fgetc(FileIn))    &&
  170.                 CouldBeKeys<21
  171.             )
  172.             {
  173.                 char*    Keystroke;
  174.  
  175.                 //Adjust to show only the keystroke
  176.                 if(    !(Keystroke=strrchr(Buffer,'P')) &&
  177.                     !(Keystroke=strrchr(Buffer,'K')) )
  178.                 {
  179.                     puts("MAJOR consistency error in keystroke scan!");
  180.                     break;
  181.                 }
  182.                 StrLoc+=(Keystroke-Buffer);
  183.  
  184.                 fprintf(FileOut,"%08lX:K:%s\n",
  185.                     StrLoc,Keystroke);
  186.                 putchar('.');
  187.                 break;
  188.             }
  189.  
  190.             //Code to output questionable strings could go here
  191.             //if desired; currently unneeded.
  192.             break;
  193.         }
  194.     }
  195. }
  196. putchar('\n');
  197. if(FilePos!=FileSize||FilePos!=ftell(FileIn))
  198.     puts("Warning: Possible error in offsets.");
  199. return RET_Normal;
  200. }
  201.  
  202. int _cdecl    main(int argc,unsigned char *argv[])
  203. {
  204.     FILE        *FileIn,*FileOut;
  205.     char        *FileInName,*FileOutName;
  206.     char        FileOutTemp[128];
  207.     unsigned char    *Buffer;
  208.     size_t        BufferSize;
  209.     int        i;
  210.     const char    *FileOpenError="Couldn't open file: %s\n";
  211.  
  212.     puts(Version);
  213.     if(argc<2)
  214.     {
  215.         puts("Usage: AFS <Input AF File> [Output AFS File]");
  216.         exit(RET_BadParms);
  217.     }
  218.  
  219.     FileInName=argv[1];
  220.  
  221.     if(argc<3)
  222.     {
  223.         char    *c;
  224.  
  225.         strcpy(FileOutTemp,FileInName);
  226.  
  227.         c=strrchr(FileOutTemp,'.');
  228.         if(!c)
  229.             c=strrchr(FileOutTemp,0);
  230.  
  231.         strcpy(c,".AFS");
  232.  
  233.         FileOutName=FileOutTemp;
  234.     }
  235.     else
  236.         FileOutName=argv[2];
  237.  
  238.  
  239.     printf(    "AF    : %s\n"
  240.         "AFS   : %s\n",FileInName,FileOutName);
  241.  
  242.     if(!(FileIn=fopen(FileInName,"rb")))
  243.     {
  244.         printf(FileOpenError,FileInName);
  245.         return RET_BadFile;
  246.     }
  247.     if(!(FileOut=fopen(FileOutName,"wt")) )
  248.     {
  249.         printf(FileOpenError,FileOutName);
  250.         return RET_BadFile;
  251.     }
  252.  
  253.     //Allocate all available near memory as buffer
  254.     if(!(Buffer=(unsigned char *)malloc(BufferSize=coreleft())))
  255.     {
  256.         puts("Could not allocate available memory as buffer!");
  257.         return RET_OutOfMemory;
  258.     }
  259.     printf("Buffer: %u bytes.\n",BufferSize);
  260.  
  261.     i=FindStrings(FileIn,FileOut,Buffer,BufferSize);
  262.  
  263.     free(Buffer);
  264.  
  265.     if(fclose(FileIn)|fclose(FileOut))
  266.     {
  267.         puts("Error closing file(s)!");
  268.         return RET_BadClose;
  269.     }
  270.  
  271.     return i;
  272. }
  273.